#include "ET++.ph"
#include "Converter.h"

#include "Class.h"
#include "Bitmap.h"
#include "DevBitmap.h"
#include "Data.h"
#include "TypeMatcher.h"
#include "ET_stdio.h"

#include "raster.xpm3"
static SmartBitmap gRasterIcon(raster);

static const Symbol cDocTypeSunRaster("SUNRASTER");
static TypeMatcher matcher(cDocTypeSunRaster, "rs", "\131\246\152\225",
								FALSE, 3000);

#define RAS_MAGIC       0x59a66a95
#define RT_STANDARD     1       /* Raw pixrect image in 68000 byte order */
#define RMT_EQUAL_RGB   1       /* red[ras_maplength/3],green[],blue[] */

//---- SunRasterConverter ------------------------------------------------------

class SunRasterConverter : public Converter {
public:
	MetaDef(SunRasterConverter);
	SunRasterConverter()
		{ }
	const char *AsString()
		{ return "Sun Raster File"; }
	Object *Convert(Data *data, Class *want);
	bool CanConvert(Data *data, Class *want)
		{ return data->Type() == cDocTypeSunRaster && want == Meta(Bitmap); }
};

NewMetaImpl0(SunRasterConverter,Converter);

Object *SunRasterConverter::Convert(Data *data, Class*)
{
	register int x;
	Point e;
	Bitmap *b= 0;
	IStream is(data->GetStreamBufForReading(), 0, TRUE);
	long magic, type, maptype;
	int maplen;
	short depth;

	magic= is.GetBigEndian(4);
	if (magic != RAS_MAGIC) {
		fprintf(stderr, "SunRasterConverter::Convert: wrong magic number\n");
		return 0;
	}

	e.x= (int) is.GetBigEndian(4);      /* width (pixels) of image */
	e.y= (int) is.GetBigEndian(4);      /* height (pixels) of image */
	depth= (short) is.GetBigEndian(4);  /* depth (1, 8, or 24 bits) of pixel */
	is.GetBigEndian(4);                 /* length (bytes) of image */
	type= is.GetBigEndian(4);           /* type of file; see RT_* below */

	maptype= is.GetBigEndian(4);        /* type of colormap; see RMT_* below */
	maplen= (int) is.GetBigEndian(4);   /* length (bytes) of following map */

	b= new Bitmap(e, depth);

	if (maptype == RMT_EQUAL_RGB) {
		if (maplen > 0) {
			byte *t= new byte[maplen];
			is.read(t, maplen);
			maplen/= 3;
			for (x= 0; x < maplen; x++) {
				RGB c(t[x], t[x+maplen], t[x+2*maplen]);
				b->ChangeRGB(x, &c);
			}
			delete t;
		} else {
			maplen= 256;
			for (x= 0; x < maplen; x++) {
				RGB c((short)x);
				b->ChangeRGB(x, &c);
			}
		}
	}

	BitmapInfo bi(e, depth, 2);
	b->GetDevBitmap()->ReadData(&bi, is);

	return b;
}

